package org.fjsei.yewu.job.service;

import org.fjsei.yewu.job.controller.model.CreateJobDetailsRequestModel;
import org.fjsei.yewu.job.listener.BusinessHoursTriggerListener;
import org.fjsei.yewu.job.listener.JobHistoryListener;
import org.fjsei.yewu.job.util.Utility;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@Component
@Slf4j
public class QuartzJobManager {

    private final Scheduler scheduler;

    //Inject the Spring Boot managed scheduler
    public QuartzJobManager(Scheduler scheduler) {
        this.scheduler = scheduler;

    }

    @PostConstruct
    public void addTriggerListener() throws SchedulerException {
        final ListenerManager listenerManager = scheduler.getListenerManager();
        listenerManager.addTriggerListener(new BusinessHoursTriggerListener());
        listenerManager.addJobListener(new JobHistoryListener());
    }
/*
Create or Update Job
* */
    public void createOrUpdateJob(CreateJobDetailsRequestModel createJobDetailsRequestModel) throws SchedulerException {
        JobKey jobKey=JobKey.jobKey(createJobDetailsRequestModel.getJobName(), createJobDetailsRequestModel.getGroupName());
        try {
            //Create JobDetail
            JobDetail jobDetail = JobBuilder.newJob(Utility.getJobClass(createJobDetailsRequestModel.getJobClassName()))
                    .withDescription(createJobDetailsRequestModel.getDescription())
                    .withIdentity(createJobDetailsRequestModel.getJobName(), createJobDetailsRequestModel.getGroupName())
//                    .requestRecovery(createJobDetailsRequestModel.isRequestRecovery())
//不用               .setJobData(null!=createJobDetailsRequestModel.getMapData()? new JobDataMap(createJobDetailsRequestModel.getMapData()) :null)
                    .build();
            // Create Trigger：必须有才能scheduleJob调度
//            Trigger trigger = TriggerBuilder.newTrigger()
//                    .withIdentity(createJobDetailsRequestModel.getJobName() + "Trigger", createJobDetailsRequestModel.getGroupName())
//                    .withSchedule(null!=createJobDetailsRequestModel.getCronExpression()? CronScheduleBuilder.cronSchedule(createJobDetailsRequestModel.getCronExpression()) :null)
//                    .withDescription(createJobDetailsRequestModel.getDescription())
////不用               .usingJobData(new JobDataMap(createJobDetailsRequestModel.getMapData()))
//                    .build();
            SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                    .withIdentity("dynamicTrigger", "dynamicGroup")
                    .startNow().build();

            //Schedule or Reschedule the above created job and trigger
            if (this.scheduler.checkExists(JobKey.jobKey(createJobDetailsRequestModel.getJobName(), createJobDetailsRequestModel.getGroupName()))) {
                // Update the existing jobs with a new trigger
                this.scheduler.rescheduleJob(new TriggerKey(createJobDetailsRequestModel.getJobName() + "Trigger", createJobDetailsRequestModel.getGroupName()), trigger);
            } else {
                //Schedule the new jobs
                this.scheduler.scheduleJob(jobDetail, trigger);
            }
//            this.scheduler.pauseJob(jobKey);    //不着急运行的：
        } catch (ClassNotFoundException classNotFoundException) {
            log.error("Job class not found {}", classNotFoundException.getException(), classNotFoundException);
            throw new SchedulerException("Job class not found " + createJobDetailsRequestModel.getJobName(), classNotFoundException);
        }
    }

    // Read Job
    public JobDetail getJobDetails(String jobName, String groupName) throws SchedulerException {
        return this.scheduler.getJobDetail(JobKey.jobKey(jobName, groupName));
    }

    // Delete Job
    public boolean deleteJob(String jobName, String groupName) throws SchedulerException {
        return this.scheduler.deleteJob(JobKey.jobKey(jobName, groupName));
    }

    // Pause Job
    public void pauseJob(String jobName, String groupName) throws SchedulerException {
        this.scheduler.interrupt(JobKey.jobKey(jobName, groupName));        //新加！
        this.scheduler.pauseJob(JobKey.jobKey(jobName, groupName));
    }

    // Resume Job
    public void resumeJob(String jobName, String groupName) throws SchedulerException {
        this.scheduler.resumeJob(JobKey.jobKey(jobName, groupName));
    }

    //Read All Jobs
    public Set<JobDetail> getAllJobDetails() throws SchedulerException {
        //Retrive all jobs keys from scheduler
        Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.anyGroup());
        //Iterate through jobs keys and fetch JobDetail for each
        Set<JobDetail> jobDetailSet = jobKeys.stream().map(jobKey -> {
            try {
                return this.scheduler.getJobDetail(jobKey);
            } catch (SchedulerException e) {
                log.error("Exception occurred {}", e.getMessage(), e);
                return null;
            }
        }).filter(Objects::nonNull).collect(Collectors.toSet());
        return jobDetailSet;
    }
}